home *** CD-ROM | disk | FTP | other *** search
/ Young Minds / Young Minds Interactive CD-ROM.ISO / sdi / scores.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-18  |  4.7 KB  |  211 lines

  1. /**********************************  scores.c  **********************/
  2. #include <pwd.h>
  3. #include <stdio.h>
  4. #include "sdi.h"
  5.  
  6. /*
  7.  * Copyright 1987 by Mark Weiser.
  8.  * Permission to reproduce and use in any manner whatsoever on Suns is granted
  9.  * so long as this copyright and other identifying marks of authorship
  10.  * in the code and the game remain intact and visible.  Use of this code
  11.  * in other products is reserved to me--I'm working on Mac and IBM versions.
  12.  */
  13.  
  14. /*
  15.  * This code is responsible 
  16.  * reading, updating, and displaying the score file.
  17.  */
  18.  
  19. #ifndef SCOREFILE
  20. #define SCOREFILE "/usr/games/lib/sdi_scores"
  21. #endif
  22.  
  23. struct scores *get_scores();
  24.  
  25. /* Already updated is used to prevent rewriting the score file more than
  26.  * once per game.
  27.  */
  28. static int already_updated = 0;
  29.  
  30. /*
  31.  * This routine is called whenever there is absolutely positively a new
  32.  * game beginning, and so if it ever gets anywhere it is ok to update
  33.  * the score file.
  34.  */
  35. new_score()
  36. {
  37.     already_updated = 0;
  38. }
  39.  
  40. /*
  41.  * Read in the old scores and insert the current game score into the file
  42.  * if it is within the top ten.  No scores are recorded in gamemaster mode.
  43.  */
  44. update_scores()
  45. {
  46.     extern int gamemaster;
  47.     struct scores *scp, *new_pos = NULL;
  48.     int i;
  49.     int score = atol((char *)panel_get_value(score_item));
  50.     int level = atol((char *)panel_get_value(level_item));
  51.     int skill = (int)panel_get_value(skill_item);
  52.     if (already_updated || gamemaster)
  53.         return;
  54.     if ((scp = get_scores()) == NULL)
  55.         return;
  56.     while (scp->score > score) {
  57.         scp += 1;
  58.     }
  59.     if (scp->score >= 0) {
  60.         struct scores *new_sc = sc_end;
  61.         while (--new_sc > scp) {
  62.             strcpy(new_sc->name, (new_sc-1)->name);
  63.             new_sc->score = (new_sc-1)->score;
  64.             new_sc->level = (new_sc-1)->level;
  65.             new_sc->skill = (new_sc-1)->skill;
  66.         }
  67.         strcpy(scp->name, USER_NAME);
  68.         scp->score = score;
  69.         scp->level = level;
  70.         scp->skill = skill;
  71.     }
  72.     if (! put_scores(sc)) {
  73.         printf("Could not write to score file '%s'.\n",scorefile);
  74.     }
  75.     already_updated = 1;
  76. }
  77.  
  78. /*
  79.  * Get the name of the current user.
  80.  */
  81. char *
  82. get_name()
  83. {
  84.     char *s;
  85.     struct passwd *p;
  86.     if (s = (char *)getlogin())
  87.         return s;
  88.     p = (struct passwd *)getpwuid(getuid());
  89.     return p->pw_name;
  90. }
  91.  
  92. /*
  93.  * Read the score file.  The format is obvious.  Exactly 11 scores are always
  94.  * returned.  The 11th is a sentinal with score '-1'.  If the score file did
  95.  * not have 10, then the extras are for user '(nobody)', score 0.
  96.  * A user name may not contain a "'".  The result of get_scores is an array
  97.  * of score structures, statically allocated.
  98.  */
  99. struct scores *
  100. get_scores()
  101. {
  102.     struct scores *scp;
  103.     char *tmpfile, *getenv();
  104.     FILE *f;
  105.     if (scorefile) {
  106.         tmpfile = scorefile;
  107.     } else if ((tmpfile = getenv("SDI_SCORES")) == NULL) {
  108.             tmpfile = scorefile;
  109.     } else {
  110.         tmpfile = "/usr/games/lib/sdi_scores";
  111.     }
  112.     /* Try hard to open some kind of score file */
  113.     if (((f = fopen(tmpfile, "r+")) == NULL)) {
  114.         tmpfile = SCOREFILE;
  115.         if (((f = fopen(tmpfile, "r+")) == NULL)) {
  116.             tmpfile = "/usr/games/lib/sdi_scores";
  117.             if ((f = fopen("/usr/games/lib/sdi_scores", "r+")) == NULL)
  118.                 return NULL;
  119.         }
  120.     }
  121.     scorefile = tmpfile;
  122.  
  123.     /* read entries */
  124.     scp = sc;
  125.     while (scp < sc_end &&
  126.         (fscanf(f, " '%[^']' %d %d %d", scp->name, &scp->score, &scp->level, &scp->skill) == 4) &&
  127.         scp->score > 0) {
  128.         scp += 1;
  129.     }
  130.     while (scp < sc_end) {
  131.         strcpy(scp->name, "(nobody)");
  132.         scp->score = 0;
  133.         scp->level = 0;
  134.         scp->skill = 0;
  135.         scp += 1;
  136.     }
  137.     scp->score = -1;
  138.     fclose(f);
  139.     return sc;
  140. }
  141.  
  142. /*
  143.  * Write a list of scores to the score file.  Never called directly, except
  144.  * by update_scores.
  145.  */
  146. put_scores(scp)
  147. struct scores *scp;
  148. {
  149.     FILE *f;
  150.     if ((f = fopen(scorefile, "w")) == NULL)
  151.         return 0;
  152.     /* write entries */
  153.     while (scp->score > 0) {
  154.         fprintf(f, "'%s' %d %d %d\n", scp->name, scp->score, scp->level, scp->skill);
  155.         scp += 1;
  156.     }
  157.     fclose(f);
  158.     return 1;
  159. }
  160.  
  161. /*
  162.  * This routine formats the score file for display when the 'scores'
  163.  * button is pressed.
  164.  */
  165. static char string_for_build_scores[1024];
  166.  
  167. char *
  168. build_scores()
  169. {
  170.     char *sp = string_for_build_scores;
  171.     struct scores *scp;
  172.     char *type_of_skill;
  173.     scp = (struct scores *)get_scores();
  174.     if (scp == NULL) {
  175.         strcpy(sp, "Could not find a score file.");
  176.     } else {
  177.         strcpy(sp, "No scores yet: play some games.");
  178.         while (scp->score > 0) {
  179.             switch(scp->skill) {
  180.                 case 0:
  181.                     type_of_skill = " novice";
  182.                     break;
  183.                 case 1:
  184.                     type_of_skill = "n occasional user";
  185.                     break;
  186.                 case 2:
  187.                     type_of_skill = "n expert";
  188.                     break;
  189.             }
  190.             sprintf(sp,
  191.                 "%s, playing as a%s, melted with score %d at level %d.\n",
  192.                 scp->name, type_of_skill, scp->score, scp->level);
  193.             scp += 1;
  194.             sp += strlen(sp);
  195.         }
  196.     }
  197.     return string_for_build_scores;
  198. }
  199.  
  200. /*
  201.  * Free the result of a call to build_scores.
  202.  */
  203. free_scores(a)
  204. char **a;
  205. {
  206. /* Oh, how I long for garbage collection. */
  207.     while (*++a) 
  208.         free(*a);
  209. }
  210.  
  211.